package com.wintop.springbootjwt.utils;

import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.wintop.springbootjwt.bean.User;
import com.wintop.springbootjwt.dao.SysUserDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.ZoneId;

@Service
@Slf4j
public class UserSecurityUtil {

    @Autowired
    SysUserDao sysUserDao;

    public boolean verifyWebToken(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            return false;
        }
        DecodedJWT decoded = JwtUtils.decoded(token);
        if (decoded == null) {
            return false;
        }
        // 从jwt payload中取出 subject 转换成 userId
        String userId = decoded.getSubject();
        // TODO 数据库操作 根据ID 查询当前用户对象
        User user = sysUserDao.getUserInfoById(userId);
        // 获取用户登陆时间
        LocalDateTime localDateTime = user.getLastLoginTime();
        String secretKey = JwtUtils.getSecretKey(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        try {
            JwtUtils.verify(secretKey, token);
        } catch (SignatureVerificationException e) {
            return false;
        } catch (TokenExpiredException e) {
            // 允许一段时间有效时间同时返回新的token
            String newToken = JwtUtils.getRefreshToken(secretKey, decoded);
            if (StringUtils.isEmpty(newToken)) {
                log.error(e.getMessage());
                return false;
            }
            log.debug("Subject : [" + userId + "] token expired, allow get refresh token [" + newToken + "]");
            response.setHeader("token", newToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;

    }

}
